#include "mapdata.h"
#include <iostream>
using namespace std;
using namespace mapdata;

/* terrain---------------------------------------
 * the basic data of a tile.
 * --------------------------------------------*/
//constructor----------------
mapdata::terrain::terrain(tp_terr tp, maprep* mrp) : placeable(mrp){
    type = tp;
    hazard = 0;
    sensorBlock = 0;
    speedBlock = 0;
    for (int i = 0; i < TER_MAX; i++)
        resources[i] = 0;
}
mapdata::terrain::terrain() : placeable(NULL){
    hazard = 0;
    sensorBlock = 0;
    speedBlock = 0;
    for (int i = 0; i < TER_MAX; i++)
        resources[i] = 0;
}
mapdata::terrain::~terrain() {
    if(parent == NULL) parent->remove(this);
}
//access---------------------
mapdata::tp_terr mapdata::terrain::gType() {
    return type;
}
float mapdata::terrain::gHazard() {
    return hazard;
}
float mapdata::terrain::gSensBlock() {
    return sensorBlock;
}
float mapdata::terrain::gSpedBlock() {
    return speedBlock;
}
int mapdata::terrain::gResource(tp_res rtp) {
    return resources[rtp];
}
//manips---------------------
void mapdata::terrain::sType(tp_terr tp) {
    type = tp;
}
void mapdata::terrain::sHazard(float ft) {
    hazard = ft;
}
void mapdata::terrain::sSensBlock(float ft) {
    sensorBlock = ft;
}
void mapdata::terrain::sSpedBlock(float ft) {
    speedBlock = ft;
}
void mapdata::terrain::rResource(tp_res rtp, int rp) {
    if (resources[rtp] >= rp) {
        resources[rtp] -= rp;
    }
}
void mapdata::terrain::sResource(tp_res rtp, int rp) {
    resources[rtp] += rp;
}

/* maprep----------------------------------------
 * holds all the terrain types and loads them
 * from the file.
 * --------------------------------------------*/
//statics--------------------
mapdata::terrain mapdata::maprep::spaceterr = terrain(mapdata::space, NULL);
//constructors---------------
mapdata::maprep::maprep() {
}
mapdata::maprep::~maprep() {
}
//access---------------------
int mapdata::maprep::gXSize() {
    return maxx;
}
int mapdata::maprep::gYSize() {
    return maxy;
}
void mapdata::maprep::gSize(int &x, int&y) {
    x = maxx;
    y = maxy;
}
mapdata::terrain* mapdata::maprep::gTerrain(int x, int y) {
    placeable* p = placeMap[make_pair(make_pair(x,y), terrZ)];
    if(p != NULL && typeid(*p) == typeid(terrain)){
        return dynamic_cast<terrain*>(p);
    }
    return &spaceterr;
}
bool maprep::isClean(int x, int y, int z){
    return placeMap[make_pair(make_pair(x,y),z)] == NULL;
}
//manips---------------------
bool maprep::add(placeable* p){
    if(isClean(p->gX(), p->gY(), p->gZ())){
        placeMap[make_pair(make_pair(p->gX(), p->gY()), p->gZ())] = p;
        return true;
    }
    return false;
}
bool maprep::remove(placeable* p){
    pair<pair<int, int>, int> pos = make_pair(make_pair(p->gX(), p->gY()), p->gZ());
    if(placeMap[pos] == p){
        placeMap.erase(pos);
        return true;
    }
    return false;
}
#define terr 1
#define play 2
#define flt 3
void mapdata::maprep::loadTerrain(string filename) {/*
    cout << "loading file " << filename << endl;
    //varblock
    Players::player* p = NULL;
    mapdata::terrain* t = NULL;
    Units::unit* u = NULL;
    int active = 0;
    int x, y;
    //open the file
    fstream file(filename.c_str(), fstream::in);
    if (file == NULL) cout << "Bad Filename";
    string tok;
    while (file.good()) {
        file >> tok;
        cout << "processing: " << tok << endl;
        if (tok.compare("PLACE") == 0) {
            file >> x >> y;
            switch (active) {
                case 0:
                    cout << "Nothing to Place at " << x << ", " << y << endl;
                    break;
                case terr:
                    cout << "placed terr at " << x << ", " << y << endl;
                    mapdata::maprep::getStaticMapRep()->setTerrain(t, x, y);
                    break;
                case play:
                    break;
                case flt:
                    u->place(x,y);
                    break;
            }
            active = 0;
        } else if (tok.compare("RES") == 0) {
        } else if (tok.compare("TERR") == 0) {
            t = new terrain();
            active = 1;
        } else if (tok.compare("ASTR") == 0) {
            if (t != NULL) t->sType(astr);
        } else if (tok.compare("NEB") == 0) {
            if (t != NULL) t->sType(neb);
        } else if (tok.compare("DEB") == 0) {
            if (t != NULL) t->sType(debris);
        } else if (tok.compare("FLEET") == 0) {
        } else if (tok.compare("PLAYER") == 0) {
            u = new Units::unit();
            active = flt;
        } else if (tok.compare("SIZE") == 0) {
            file >> x >> y;
            maxx = x;
            maxy = y;
            cout << "setting size to " << x << ", " << y << endl;
        } else if(tok.compare("#")){
        }
    }
    file.close();*/
}
/* placeable-------------------------------------
 * represents an item that can be placed on the map
 * --------------------------------------------*/
//constructors---------------
placeable::placeable(maprep* pmp){
    parent = pmp;
    x = 0;
    y = 0;
}
placeable::placeable(int _x, int _y, maprep* pmp){
    parent = pmp;
    x = _x;
    y = _y;
    parent->add(this);
}
placeable::~placeable(){
    if(parent != NULL) remove();
}
//access---------------------
void placeable::gPos(int& _x, int& _y){
    _x = x;
    _y = y;
}
void placeable::gPos(int& _x, int& _y, int& _z){
    _x = x;
    _y = y;
    _z = z;
}
int placeable::gX(){
    return x;
}
int placeable::gY(){
    return y;
}
int placeable::gZ(){
    return z;
}
//manips---------------------
bool placeable::place(int _x, int _y){
    if(parent != NULL){
        if(!parent->isClean(_x, _y, z))
            return false;
        parent->remove(this);
        x = _x; y = _y;
        parent->add(this);
        return true;
    }
    x = _x; y = _y;
    return true;
}
void placeable::remove(){
    if(parent != NULL) parent->remove(this);
    x = -1;
    y = -1;
}
void placeable::setZ(int _z){
    z = _z;
}